using Abc.Core;
using Abc.Core.Entities;

using Furion.DatabaseAccessor;
using Furion.DependencyInjection;

using Mapster;

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Tool;

namespace Abc.Application
{
    /// <summary>
    /// 角色
    /// </summary>
    [ApiDescriptionSettings(Name = "Role")]
    //[Injection(Proxy = typeof(LogDispatchProxy))]
    [ServiceFilter(typeof(ApiActionFilterAttribute))]
    public class RoleService : IRoleService, ITransient
    {
        private readonly ILogger<RoleService> _logger;
        private readonly IRepository<Role> _roleRepository;
        private readonly ICacheService _cacheService;

        public RoleService(ILogger<RoleService> logger
        //, IMemoryCache memoryCache
        , IRepository<Role> roleRepository
        , ICacheService cacheService)
        {
            _logger = logger;
            // _memoryCache = memoryCache;
            //_memoryCache =  App.GetService<IMemoryCache>();
            _roleRepository = roleRepository;
            _cacheService = cacheService;
        }

        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultData<string>> InsertOrUpdate(RoleInput input)
        {
            var resultdata = new ResultData<string>();
            if (input.Id > 0)
            {
                var dbentity = await _roleRepository.FindAsync(input.Id);
                input.Adapt(dbentity);
                await _roleRepository.UpdateAsync(dbentity);
            }
            else
            {
                var newEntity = await _roleRepository.InsertAsync(input.Adapt<Role>());
            }
            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        public async Task<ResultData<string>> Delete(int id)
        {
            var resultdata = new ResultData<string>();
            await _roleRepository.DeleteAsync(id);

            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="id"></param>
        public async Task<RoleOut> Find(int id)
        {
            var dbentity = await _roleRepository.FindAsync(id);
            return dbentity.Adapt<RoleOut>();
        }

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="id"></param>
        public async Task<RoleOut> Get(int id)
        {
            var dbentity = await _roleRepository.FirstOrDefaultAsync(o => o.Id == id, tracking: false);
            if (dbentity == null) return null;
            return dbentity.Adapt<RoleOut>();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        public async Task<PagedListToLayui<RoleOut>> GetAllByPageToLayui(RoleQuery searchQuery)
        {
            //var queryable= _roleRepository.DetachedEntities.AsQueryable();
            //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
            //{
            //    var kw = searchQuery.KeyWords.ToLower();
            //    queryable = queryable.Where(o => o.No.Contains(kw));
            //}

            var pageResult = _roleRepository.DetachedEntities.AsQueryable().OrderByDescending(o => o.Id).ProjectToType<RoleOut>();
            return await pageResult.ToPagedListToLayuiAsync(searchQuery.Page, searchQuery.Limit);
        }

        /// <summary>
        /// 设置角色权限
        /// </summary>
        /// <param name="input">输入role对象</param>
        /// <returns></returns>
        public async Task<ResultData<string>> SetRolePermission(RoleInput input)
        {
            var resultdata = new ResultData<string>();
            var dbrole = await _roleRepository.Include(o => o.Permissions).FirstOrDefaultAsync(o => o.Id == input.Id);
            if (dbrole == null)
            {
                dbrole = input.Adapt<Role>();
                dbrole.RolePermissions = new List<RolePermission>();
                dbrole.Permissions = new List<Permission>();
            }
            else
            {
                input.Adapt(dbrole);
            }

            var permissions = input.Permissionstrs.ToIntList(new char[] { ',' });
            foreach (var permissionid in dbrole.Permissions.Select(o => o.Id).ToList())
            {
                var permission = dbrole.Permissions.First(o => o.Id == permissionid);
                if (permissions.All(o => o != permissionid)) dbrole.Permissions.Remove(permission);
            }
            dbrole.RolePermissions = new List<RolePermission>();
            foreach (var permissionid in permissions)
            {
                dbrole.RolePermissions.Add(new RolePermission() { PermissionId = permissionid });
            }
            if (dbrole.Id <= 0)
            {
                await _roleRepository.InsertAsync(dbrole);
            }
            resultdata.Succeeded = true;
            return resultdata;
        }

        /// <summary>
        /// 获取角色 权限 Dtree 树
        /// </summary>
        /// <param name="menuid"></param>
        /// <param name="typecode"></param>
        /// <returns></returns>
        public async Task<Dtree> GetRoleDtreeCheck(int roleid = 0)
        {
            Role role = null;
            if (roleid > 0)
            {
                var roleentities = await _cacheService.GetRoleEntities();
                role = roleentities.FirstOrDefault(o => o.Id == roleid);
            }
            var menus = await _cacheService.GetMenuEntities();

            var rolePermissions = role != null ? role.Permissions.ToList() : new List<Permission>();
            var dtreeitems = GetDtreeCheckItems(menus, rolePermissions);

            HandleChekedSelectState(dtreeitems);

            var dtree = new Dtree();
            dtree.data = dtreeitems;
            return dtree;
        }

        /// <summary>
        /// 生成菜单树节点
        /// </summary>
        /// <param name="menus"></param>
        /// <param name="rolePermissions"></param>
        /// <param name="pid"></param>
        /// <returns></returns>
        private List<DtreeCheckItem> GetDtreeCheckItems(List<Menu> menus, List<Permission> rolePermissions, string pid = "")
        {
            var dtreecheckitems = new List<DtreeCheckItem>();
            foreach (var menu in menus.Where(o => o.PMId == pid.ToString()))
            {
                DtreeCheckItem dtreeitem = new DtreeCheckItem()
                {
                    id = $"m_{menu.MId}",
                    title = menu.Name,
                    parentId = $"m_{pid}",
                    last = false,
                    checkArr = new Dictionary<string, string>()
                    {
                       { "type","0"},
                       { "checked",$"0" }
                    }
                };
                if (menus.Any(o => o.PMId == menu.MId))
                {
                    dtreeitem.children = GetDtreeCheckItems(menus, rolePermissions, menu.MId);
                }
                else
                {
                    if (menu.Permissions.Any())
                    {
                        dtreeitem.children = GetPermissionItems(menu, rolePermissions);
                    }
                    else
                    {
                        //最后一个节点
                        dtreeitem.last = true;
                    }
                }
                dtreecheckitems.Add(dtreeitem);
            }
            return dtreecheckitems;
        }

        /// <summary>
        /// 生成权限树节点
        /// </summary>
        /// <param name="menu"></param>
        /// <param name="rolePermissions"></param>
        /// <returns></returns>
        private List<DtreeCheckItem> GetPermissionItems(Menu menu, List<Permission> rolePermissions)
        {
            var dtreecheckitems = new List<DtreeCheckItem>();
            foreach (var permission in menu.Permissions)
            {
                DtreeCheckItem dtreeitem = new DtreeCheckItem()
                {
                    id = $"{permission.Id}",
                    title = permission.Name,
                    parentId = $"m_{menu.MId}",
                    last = true,
                };
                if (rolePermissions.Any(o => o.Id == permission.Id))
                {
                    //角色中已存在，选中
                    dtreeitem.checkArr = new Dictionary<string, string>()
                    {
                       { "type","0"},
                       { "checked",$"1" }
                    };
                }
                else
                {
                    //角色中不存在，不选中
                    dtreeitem.checkArr = new Dictionary<string, string>()
                    {
                       { "type","0"},
                       { "checked",$"0" }
                    };
                }
                dtreecheckitems.Add(dtreeitem);
            }
            return dtreecheckitems;
        }

        /// <summary>
        /// 处理上级cheked选中状态
        /// </summary>
        /// <param name="dtreeCheckItems"></param>
        /// <returns></returns>
        private bool HandleChekedSelectState(List<DtreeCheckItem> dtreeCheckItems)
        {
            //是否有选中的权限
            var IsCheckedPermission = false;
            foreach (var dtreeCheckItem in dtreeCheckItems)
            {
                if (dtreeCheckItem.children.Any())
                {
                    //还有下级

                    IsCheckedPermission = HandleChekedSelectState(dtreeCheckItem.children);
                    if (IsCheckedPermission)
                    {
                        dtreeCheckItem.checkArr = new Dictionary<string, string>()
                        {
                           { "type","0"},
                           { "checked",$"1" }
                        };
                    }
                }
                else
                {
                    //没有下级了、到权限了
                    if (!dtreeCheckItem.id.StartsWith("m_"))
                    {
                        if (dtreeCheckItem.checkArr.ContainsKey("checked"))
                        {
                            if (dtreeCheckItem.checkArr["checked"] == "1")
                            {
                                IsCheckedPermission = true;
                            }
                        }
                    }
                    if (IsCheckedPermission) break;//只要有一个权限选中即为true
                }
            }

            return IsCheckedPermission;
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        public async Task<ResultData<string>> SetState(int id, bool state, string field)
        {
            var resultdata = new ResultData<string>();
            var entity = await _roleRepository.FirstOrDefaultAsync(o => o.Id == id);

            switch (field.ToLower())
            {
                case "isenable":
                    {
                        entity.IsEnable = state;
                    }
                    break;
                //case "isdeleted":
                //    {
                //        entity.IsDeleted = state;
                //    }
                //    break;
                default:
                    break;
            }

            resultdata.Succeeded = true;
            resultdata.Errors = "操作成功";
            return resultdata;
        }

        /// <summary>
        /// 查询所有
        /// </summary>
        /// <returns></returns>
        public async Task<List<RoleOut>> GetAll()
        {
            var entities = await _cacheService.GetRoleEntities();

            return entities.Adapt<List<RoleOut>>();
        }

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Insert(RoleInput input)
        //{
        //    var resultdata = new ResultData<string>();
        //    var newEntity = await _roleRepository.InsertAsync(input.Adapt<Role>());
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Update(int id,RoleInput input)
        //{
        //    var resultdata=new ResultData<string>();
        //    var dbentity = await _roleRepository.FindAsync(id);
        //    input.Adapt(dbentity);
        //    await _roleRepository.UpdateAsync(dbentity);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Inserts(List<RoleInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var dbaddinputs = inputs.Adapt<List<Role>>();
        //    await _roleRepository.InsertAsync(dbaddinputs);
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Updates(List<RoleInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var ids = inputs.Select(o => o.Id).ToList();
        //    var dbentitys = await _roleRepository.Where(u => ids.Any(a => a == u.Id)).ToListAsync();
        //    inputs.Adapt(dbentitys);
        //    await _roleRepository.UpdateAsync(dbentitys);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> InsertOrUpdates(List<RoleInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    if (inputs.Any(o => o.Id > 0))
        //    {
        //        var updates = inputs.Where(o => o.Id > 0);
        //        var ids = updates.Select(o=>o.Id).ToList();
        //        var dbentity =  _roleRepository.Where(o=> ids.Any(a=>a==o.Id));
        //        inputs.Adapt(dbentity);
        //        await  _roleRepository.UpdateAsync(dbentity);
        //    }
        //    else
        //    {
        //       var adds = inputs.Where(o => o.Id <= 0);
        //       await _roleRepository.InsertAsync(adds.Adapt<List<Role>>());
        //
        //    }
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        //
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //public async Task<List<RoleDto>> GetAll()
        //{
        //    var entities = _roleRepository.DetachedEntities.AsQueryable().ProjectToType<RoleDto>();
        //    var datas= await entities.ToListAsync();
        //    datas.SetMemberCache("Table_Role");
        //    return datas;
        //}
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //public async Task<PagedList<RoleDto>> GetAllByPage(RoleQuery searchQuery)
        //{
        //    //var queryable= _roleRepository.DetachedEntities.AsQueryable(tracking:false);
        //    //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        //    //{
        //    //    var kw = searchQuery.KeyWords.ToLower();
        //    //    queryable = queryable.Where(o => o.No.Contains(kw));
        //    //}
        //    var pageResult = _roleRepository.DetachedEntities.AsQueryable().OrderByDescending(o => o.Id).ProjectToType<RoleDto>();
        //
        //    return await pageResult.ToPagedListAsync(searchQuery.Page, searchQuery.Limit);
        //}
        //
        //
        //
        //

        #endregion 默认未启用
    }

    public interface IRoleService
    {
        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<ResultData<string>> InsertOrUpdate(RoleInput input);

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        Task<ResultData<string>> Delete(int id);

        /// <summary>
        /// 查询一条
        /// </summary>
        /// <param name="id"></param>
        Task<RoleOut> Find(int id);

        /// <summary>
        /// 查询一条
        /// </summary>
        /// <param name="id"></param>
        Task<RoleOut> Get(int id);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        Task<PagedListToLayui<RoleOut>> GetAllByPageToLayui(RoleQuery searchQuery);

        /// <summary>
        /// 设置角色权限
        /// </summary>
        /// <param name="input">输入role对象</param>
        /// <returns></returns>
        Task<ResultData<string>> SetRolePermission(RoleInput input);

        /// <summary>
        /// 获取角色 权限 Dtree 树
        /// </summary>
        /// <param name="menuid"></param>
        /// <param name="typecode"></param>
        /// <returns></returns>
        Task<Dtree> GetRoleDtreeCheck(int roleid = 0);

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        Task<ResultData<string>> SetState(int id, bool state, string field);

        /// <summary>
        /// 查询所有
        /// </summary>
        /// <returns></returns>
        Task<List<RoleOut>> GetAll();

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Insert(RoleInput input);
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Update(int id,RoleInput input);
        ///// <summary>
        ///// 新增或更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Inserts(List<RoleInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Updates(List<RoleInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> InsertOrUpdates(List<RoleInput> inputs);
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //Task<List<RoleDto>> GetAll();
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //Task<PagedList<RoleDto>> GetAllByPage(RoleQuery searchQuery);

        #endregion 默认未启用
    }
}